﻿using Common.Enum;
using Common.Log;
using DryWCS.Biz.Base;
using DryWCS.Biz.Http;
using DryWCS.Model.Enum;
using DryWCS.Model.Flatcar;
using DryWCS.Model.Stacker;
using DryWCS.Model.WMS;
using DryWCS.Service.GlobalVariable;
using DryWCS.Service.WMS;
using Sharp7;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DryWCS.Biz
{
    public class StackerMachine : MachineBase
    {

        public StackerMachine(PLCInfo plcInfo) : base(plcInfo)
        {
        }
        //192.168.102.100
        private const int READDBNUM = 601;
        private const int WRITEDBNUM = 600;

        private int taskFeedbackCache = -1;
        private int taskStatusCache = -1;

        WareHouseCellInfoService wareHouseCellInfoService = new WareHouseCellInfoService();

        public void Start()
        {
            Read();//刷新变量
            ExecuteStackerTask();//执行堆垛机任务
            //ReportToWMS();//任务结束后，向WMS过账
        }

        #region Read
        public override void Read()
        {
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        GV.StackerData.Connected = client.Connected;

                        if (!client.Connected)
                        {
                            Connect();
                            Thread.Sleep(500);
                        }

                        byte[] buffer = new byte[24];
                        int feedback = -1;
                        int taskStatus = -1;
                        int res = client.DBRead(READDBNUM, 0, buffer.Length, buffer);
                        if (res == 0)
                        {
                            Util.Util.AnalysisBytes(GV.StackerData, buffer); //解析读到的PLC数据                         
                            feedback = GV.StackerData.TaskFeedback;
                            taskStatus = GV.StackerData.TaskStatus;
                            ProcessTaskFeedback(feedback);
                            ProcessFinishSignal(taskStatus);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogHelper.WriteLog($"{PLCInfo.Name}读取DB块异常", ex);
                    }

                    Thread.Sleep(500);
                }
            });
        }
        #endregion

        #region 堆垛机复位
        private void ProcessTaskFeedback(int feedback)
        {
            if (feedback == taskFeedbackCache)
            {
                return;
            }

            if (feedback != 1)
            {
                Retry(5, ResetTaskSignal);
            }

            taskFeedbackCache = feedback;
        }

        
        private bool ResetTaskSignal()
        {
            try
            {
                byte[] buffer = new byte[2];
                S7.SetIntAt(buffer, 0, 1);
                int res = client.DBWrite(WRITEDBNUM, 0, buffer.Length, buffer);
                if (res == 0)
                {
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("堆垛机复位任务信号异常", ex);
                return false;
            }
        }
        #endregion

        #region 反馈任务结束
        private void ProcessFinishSignal(int taskStatus)
        {
            if (taskStatus == taskStatusCache)
            {
                return;
            }

            if (taskStatus == 6 || taskStatus == 1)
            {
                Retry<short>(5, ResetFinishSignal, (short)taskStatus);

                if (taskStatus == 6)
                {
                    GV.StackerIsLock = false;// 释放堆垛机
                }
            }

            if (taskStatus == 7)// 异常结束
            {
                // 异常需要人工手动释放
                // GV.StackerIsLock = false;// 释放堆垛机
                // TODO 向wms反馈异常结束原因
                Retry<short>(5, ResetFinishSignal, (short)taskStatus);
            }

            taskStatus = taskStatusCache;
        }

        private bool ResetFinishSignal(short signal)
        {
            try
            {
                #region 处理任务表
                if (signal == 6 || signal == 7)
                {
                    StackerTaskEntity stackerTask = stackerTaskService.GetByWMSOrderID(GV.StackerData.TaskID);

                    if (stackerTask != null)
                    {
                        //if (stackerTask.EndMachineID == 1002)//B点出库，解锁平板车任务，将货物从B点送至箔绕区
                        //{
                        //    FlatcarTaskEntity flatcarTask = flatcarTaskService.GetFirstByWMSID(GV.StackerData.TaskID);

                        //    if (flatcarTask != null)
                        //    {
                        //        flatcarTask.IsLock = false;
                        //        flatcarTaskService.Update(flatcarTask);
                        //    }
                        //}

                        if (signal == 7)
                        {
                            stackerTask.Status = TaskStatusEnum.异常;
                           //  stackerTask.Remark = GV.StackerData.Exception.ToString();
                        }
                        else
                        {
                            if(stackerTask.EndMachineID == 0)//终点是货位
                            {
                                WareHouseCellInfoModel cellInfoModel = wareHouseCellInfoService.GetBy(1, stackerTask.EndLineNo, stackerTask.EndColNo, stackerTask.EndLayerNo);
                                if (cellInfoModel != null)
                                {
                                    cellInfoModel.POS_STATUS = 1;
                                    wareHouseCellInfoService.Update(cellInfoModel);
                                }
                            }
                            if (stackerTask.StartMachineID == 0)//起点是货位
                            {
                                WareHouseCellInfoModel cellInfoModel = wareHouseCellInfoService.GetBy(1, stackerTask.StartLineNo, stackerTask.StartColNo, stackerTask.StartLayerNo);
                                if (cellInfoModel != null)
                                {
                                    cellInfoModel.POS_STATUS = 0;
                                    wareHouseCellInfoService.Update(cellInfoModel);
                                }
                            }
                           
                            stackerTask.Status = TaskStatusEnum.执行完成;

                        }
                        stackerTask.EndTime = DateTime.Now;
                        stackerTaskService.Update(stackerTask);
                    }
                }
                #endregion

                byte[] buffer = new byte[2];
                S7.SetIntAt(buffer, 0, signal);
                int res = client.DBWrite(WRITEDBNUM, 22, buffer.Length, buffer);
                if (res == 0)
                {
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("堆垛机复位任务完成信号异常", ex);
                return false;
            }
        }
        #endregion

        #region 向WMS过账
        private void ReportToWMS()
        {
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        StackerTaskEntity stackerTask = stackerTaskService.GetFirstByStatus(TaskStatusEnum.执行完成);
                        if (stackerTask != null)
                        {

                            bool res = HttpClient.ResportToWMS(stackerTask.WMSOrderId.ToString());//过账
                            if (res)
                            {
                                StackerTaskHisEntity stackerTaskHis = mapper.Map<StackerTaskHisEntity>(stackerTask);
                                stackerTaskHisService.Insert(stackerTaskHis);//备份历史表
                                stackerTaskService.Delete(stackerTask);//删除原有数据
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogHelper.WriteLog("WMS过账或者备份堆垛机数据表异常", ex);
                    }

                    Thread.Sleep(1000);
                }
            });

        }

        #endregion

        #region 下发堆垛机任务
        private void ExecuteStackerTask()
        {
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        StackerTaskEntity stackerTask = stackerTaskService.GetFirstByStatus(TaskStatusEnum.未执行);
                        if (stackerTask == null)//可执行任务列表为空
                        {
                            Thread.Sleep(500);
                            continue;
                        }

                        if (GV.StackerData.Mode != 2 || GV.StackerData.Status != 1 || GV.StackerIsLock)//设备不在联机状态或者不在空闲状态或者堆垛机被锁定
                        {
                            Thread.Sleep(500);
                            continue;
                        }

                        if (stackerTask.StartMachineID == 1001)// 入库
                        {
                            //if (!(GV.ConveyorData.Conveyor_1001_Tray == 1 && GV.ConveyorData.Conveyor_1001_Stock == 1)) //!(有托盘且有货)
                            //{
                            //    Thread.Sleep(500);
                            //    continue;
                            //}
                        }

                        if (stackerTask.EndMachineID == 1002)// 1002出库
                        {
                            //if (!(GV.ConveyorData.Conveyor_1002_Tray == 1 && GV.ConveyorData.Conveyor_1002_Stock == 0)) //!(有托盘且无货)
                            //{
                            //    Thread.Sleep(500);
                            //    continue;
                            //}
                        }

                        if (stackerTask.EndMachineID == 1003)// 1003出库
                        {
                            //if (!(GV.ConveyorData.Conveyor_1003_Tray == 1 && GV.ConveyorData.Conveyor_1003_Stock == 0)) //!(有托盘且无货)
                            //{
                            //    Thread.Sleep(500);
                            //    continue;
                            //}
                        }

                        StackerTaskParam stackerTaskParam = new StackerTaskParam
                        {
                            TaskID = stackerTask.WMSOrderId,
                            Signal = (short)stackerTask.TaskType,
                            StartMachineID = (short)stackerTask.StartMachineID,
                            StartLineNo = (short)stackerTask.StartLineNo,
                            StartLayerNo = (short)stackerTask.StartLayerNo,
                            StartColNo = (short)stackerTask.StartColNo,
                            EndMachineID = (short)stackerTask.EndMachineID,
                            EndLineNo = (short)stackerTask.EndLineNo,
                            EndLayerNo = (short)stackerTask.EndLayerNo,
                            EndColNo = (short)stackerTask.EndColNo
                        };

                        bool res = IssueTask(stackerTaskParam);
                        if (res)//发送成功，更新任务状态
                        {
                            GV.StackerIsLock = true;//锁定堆垛机
                            stackerTask.Status = TaskStatusEnum.执行中;
                            stackerTaskService.Update(stackerTask);
                        }

                    }
                    catch (Exception ex)
                    {
                        LogHelper.WriteLog("堆垛机执行任务异常", ex);
                    }

                    Thread.Sleep(500);
                }
            });
        }

        private bool IssueTask(StackerTaskParam task)
        {
            try
            {
                byte[] buffer = new byte[22];
                S7.SetIntAt(buffer, 0, task.Signal);//信号
                S7.SetDIntAt(buffer, 2, task.TaskID);//任务ID
                S7.SetIntAt(buffer, 6, task.StartMachineID);//取货设备ID
                S7.SetIntAt(buffer, 8, task.StartLineNo);//取货排
                S7.SetIntAt(buffer, 10, task.StartLayerNo);//取货层
                S7.SetIntAt(buffer, 12, task.StartColNo);//取货列
                S7.SetIntAt(buffer, 14, task.EndMachineID);//放货设备ID
                S7.SetIntAt(buffer, 16, task.EndLineNo);//放货排
                S7.SetIntAt(buffer, 18, task.EndLayerNo);//放货层
                S7.SetIntAt(buffer, 20, task.EndColNo);//返货列

                int res = client.DBWrite(WRITEDBNUM, 0, buffer.Length, buffer);
                if (res == 0)
                {
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("下发堆垛机任务异常", ex);
                return false;
            }
        }
        #endregion

    }

    public class StackerTaskParam
    {
        /// <summary>
        /// 1.复位 2.入库 3.出库 4.盘拣 5.移动
        /// </summary>
        public short Signal { get; set; }

        public int TaskID { get; set; }

        public short StartMachineID { get; set; }

        public short StartLineNo { get; set; }

        public short StartLayerNo { get; set; }

        public short StartColNo { get; set; }

        public short EndMachineID { get; set; }

        public short EndLineNo { get; set; }

        public short EndLayerNo { get; set; }

        public short EndColNo { get; set; }
    }
}
